/*
 * Copyright 2011 The Rusted Roof, LLC.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.proteusframework.platformservice.persistence.packaging;

import org.proteusframework.core.util.Assert;
import org.proteusframework.platformservice.persistence.api.*;
import org.proteusframework.platformservice.persistence.api.messagebean.IMessageBeanDescriptorVisitor;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public final class BinaryPackageVisitor implements IPackagingVisitor
{
    private static Logger logger = Logger.getLogger(BinaryPackageVisitor.class.getName());

    private IMessageBeanDescriptorVisitor messageBeanSerializer;
    private IProjectManagerVisitor projectDescriptorSerializer;
    private IVFSVisitor vfsFileSerializer;
    private ZipOutputStream zout;
    private int direction;
    private boolean includeData;

    public BinaryPackageVisitor(final int direction, boolean includeData)
    {
        this.direction = direction;
        this.includeData = includeData;
    }

    @Override
    public void startVisit(final File packageFile) throws IOException
    {
        Assert.parameterNotNull(packageFile, "Parameter 'packageFile' must not be null");

        switch (direction)
        {
            case DIRECTION_IN:
                ZipFile packageFile1 = new ZipFile(packageFile);

                // Direction is indicated by virtual of a ZipFile instead of a ZipOutputStream
                projectDescriptorSerializer = new ProjectManagerZipSerializer(packageFile1);
                vfsFileSerializer = new VFSFileZipSerializer(packageFile1);
                messageBeanSerializer = new MessageBeanDescriptorZipSerializer(packageFile1, includeData);
                break;
            case DIRECTION_OUT:
                zout = new ZipOutputStream(new FileOutputStream(packageFile));
                zout.setComment("Proteus Framework Persistence Binary Package, Agnostic Format");
                zout.setLevel(ZipOutputStream.STORED);

                // Direction is indicated by virtual of a ZipFile instead of a ZipOutputStream
                projectDescriptorSerializer = new ProjectManagerZipSerializer(zout);
                vfsFileSerializer = new VFSFileZipSerializer(zout);
                messageBeanSerializer = new MessageBeanDescriptorZipSerializer(zout, includeData);
                break;
        }
    }

    @Override
    public void visitMessageBeanManager(IMessageBeanManager messageBeanManager) throws IOException
    {
        logger.fine("Visiting message bean manager...");
        messageBeanManager.accept(messageBeanSerializer);
    }

    @Override
    public void visitVFSManager(IVFSManager vfsManager) throws IOException
    {
        logger.fine("Visiting VFS manager...");
        vfsManager.accept(vfsFileSerializer);
    }

    @Override
    public void visitProjectManager(IProjectManager projectManager) throws IOException
    {
        logger.fine("Visiting project manager...");
        projectManager.accept(projectDescriptorSerializer);
    }

    @Override
    public void endVisit() throws IOException
    {
        logger.fine("Closing package...");
        if (direction == DIRECTION_OUT)
        {
            zout.flush();
            zout.close();

        }
    }
}
